Implementation for SEP-2243 Http Standardization#1553
Open
mikekistler wants to merge 10 commits into
Open
Conversation
Address multiple specification compliance issues identified during review: Source fixes: - Fix tab (0x09) encoding: tabs now trigger Base64 encoding per spec - Add client-side tool schema validation: tools with invalid x-mcp-header annotations (non-object schemas, missing properties) are filtered out - Remove server empty-header early-return that skipped validation - Fix numeric precision loss: use GetRawText()/ToJsonString() instead of GetDouble()/GetValue<double>() for header value extraction - Implement proper version gating: only DRAFT-2026-v1 requires header validation on server side (client always sends headers unconditionally) - Add server-side invalid character validation for header values Test additions: - 22 new integration tests in Sep2243HeaderTests.cs covering encoding, validation, tool filtering, and end-to-end header scenarios - 4 new server conformance tests for draft version header validation - 2 new client conformance tests for tool filtering and header sending - 2 new unit tests for tab encoding behavior - 1 new theory for SupportsStandardHeaders version gating - Fix ConformanceClient to handle toolCalls array format and add prompts/list + prompts/get calls for http-standard-headers scenario Other: - Add *.lscache to .gitignore
The http-standard-headers, http-custom-headers, and http-invalid-tool-headers client scenarios and http-header-validation, http-custom-header-server-validation server scenarios require conformance package >= 0.1.16 which is not yet published to npm. Add NodeHelpers.GetConformanceVersion() that runs 'conformance --version' and NodeHelpers.IsConformanceVersionAtLeast() for runtime version checks. Tests auto-skip when the harness is too old and auto-run once the package is updated. Works with both npm-published and local file: references.
…rash The Node.js conformance runner can crash during cleanup on Windows with a libuv assertion (UV_HANDLE_CLOSING) that produces a non-zero exit code even when all conformance checks passed. This change adds a fallback that parses the 'Test Results:' summary in stdout to determine success when the process exit code is non-zero. Also updates package-lock.json with latest dependency versions.
McpHeaderEncoder is a shared utility used by both client-side (McpHeaderExtractor) and server-side (StreamableHttpHandler) code. Placing it in the Client namespace forced server code to reference ModelContextProtocol.Client, creating a misleading dependency. Move it to ModelContextProtocol.Protocol alongside McpHttpHeaders where it logically belongs as a transport-level concern.
- Add typed EncodeValue overloads (string?, bool, long, double) to McpHeaderEncoder for stronger compile-time safety and non-nullable return types - Change MinVersionForStandardHeaders from const to static readonly to prevent const-inlining across assemblies when the version string changes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
Implements SEP-2243 (HTTP Header Standardization) for both client and server Streamable HTTP transports. This enables network infrastructure (load balancers, proxies, gateways) to make routing and filtering decisions based on MCP request metadata without parsing the JSON-RPC body.
Fixes #1541.
Changes
Protocol & Constants
McpHttpHeadersstatic class with standard header name constants (Mcp-Method,Mcp-Name,Mcp-Param-*, etc.)DRAFT-2026-v1as a supported protocol version for header enforcementMcpErrorCode.HeaderMismatch(-32001) for header validation failuresClient-side (ModelContextProtocol.Core)
StreamableHttpClientSessionTransportemitsMcp-Method,Mcp-Name, andMcp-Param-*headers on all outgoing POST requestsMcpHeaderEncoderhandles value encoding (plain ASCII pass-through, Base64 wrapping with=?base64?...?=sentinel for non-ASCII/control characters/leading-trailing whitespace)McpHeaderExtractor(internal) readsx-mcp-headerannotations from tool schemas and adds correspondingMcp-Param-{Name}headerstools/listand rejects tools with invalidx-mcp-headerannotations (empty names, invalid characters, case-insensitive duplicates, non-primitive types)Server-side (ModelContextProtocol.AspNetCore)
StreamableHttpHandlervalidates incomingMcp-MethodandMcp-Nameheaders match the JSON-RPC body (enforced only forDRAFT-2026-v1+)Mcp-Param-*custom headers against tool schemax-mcp-headerannotations and body argument values400 Bad RequestwithHeaderMismatch(-32001) JSON-RPC error on validation failureTool Authoring (ModelContextProtocol.Core)
[McpHeader("Name")]attribute marks tool parameters for header mirroringAIFunctionMcpServerToolemitsx-mcp-headerextension in the tool's JSON schema for annotated parametersProtocol Version Gating
Header validation is only enforced when the client's
MCP-Protocol-Versionheader isDRAFT-2026-v1or later. Clients on older protocol versions are unaffected. The client always sends headers on Streamable HTTP transport regardless of version (additive, non-breaking).New Public API Surface
ModelContextProtocol.Protocol.McpHttpHeaders(static class)ModelContextProtocol.Protocol.McpHeaderEncoder(static class)ModelContextProtocol.Server.McpHeaderAttribute(attribute)ModelContextProtocol.McpErrorCode(enum addition)How Has This Been Tested?
The PR includes comprehensive tests covering:
McpHeaderEncoderTests— encode/decode round-trips, Base64 edge cases, type conversion, empty/null handlingMcpHeaderAttributevalidation and schema generationSep2243HeaderTests— server-side header validation (method/name mismatch, missing headers, Base64 encoding, version gating, custom parameter headers)Conformance tests are aligned with conformance repo PR #259.
All existing tests continue to pass (~8,000+ across net8.0, net9.0, net10.0, net472).
Breaking Changes
No breaking changes.
Types of changes
Checklist